﻿ using System;
using System.Collections;

namespace Lesson1_ArrayList
{
    //背包类
    class Backpack 
    {
        ArrayList backPack = new ArrayList();//声明ArrayList容器，用于存储物品
        public int wallet = 1000;//钱包
       /// <summary>
       /// 购买物品
       /// </summary>
       /// <param name="物品"></param>
       /// <param name="所需金钱"></param>
        public void Buy(object items,int money)
        {
            if (wallet>money)
            {
                backPack.Add(items);
                wallet -= money;
                Console.WriteLine("购买成功");
            }
            else Console.WriteLine("余额不足");

            Console.WriteLine("当前余额为:" + wallet);

        }
        /// <summary>
        /// 卖出物品
        /// </summary>
        /// <param name="物品"></param>
        /// <param name="所得金钱"></param>
        public void Sale(object items, int money)
        {
            //判断背包有无这个物品
            if (backPack.IndexOf(items)!=-1)
            {
                backPack.Remove(items);
                wallet += money;
                Console.WriteLine("卖出成功");
                Console.WriteLine("当前余额为:" + wallet);
            }else Console.WriteLine("背包没有这个物品");


        }

        /// <summary>
        /// 显示物品
        /// </summary>
        public void Show()
        {
            if (backPack.Count>0)
            {
                Console.WriteLine("显示背包物品：");
                foreach (var item in backPack)
                {
                    Console.WriteLine(item);
                }
            }else Console.WriteLine("背包是空的");

        }


    }

    class Program
    {
        static void Main(string[] args)
        {
            #region 知识点一 ArrayList的本质
            //ArrayList是一个C#为我们封装好的类
            //它的本质是一个object类型的数组
            //ArrayList类帮助我们实现了很多方法
            //比如数组的增删查改
            #endregion

            #region 知识点二 申明
            //需要引用命名空间 using System.Collections;
            ArrayList array = new ArrayList();
            #endregion

            #region 知识点三 增删查改

            #region 增
            //可以加任意类型 包括一个类
            //现在的Add方法是只能一个一个的加
            array.Add(1);
            array.Add("123");
            array.Add(true);
            array.Add(new object());
            array.Add(new Backpack());
            array.Add(1);
            array.Add(true);

            ArrayList array2 = new ArrayList();
            array2.Add(123);
            array2.Add(456);
            //范围增加 (批量增加 把另一个list容器里面的 内容加到后面，类似于字符串的拼接)
            array.AddRange(array2);
            //插入 在下标1的位置插入一个"123456"的值
            //array.Insert(1, "123456");
            //范围插入 把另一个容器List里的内容直接插入到当前位置
            //array.InsertRange(2,array2);
            #endregion

            #region 删
            //移除指定元素 从头找 找到删
            array.Remove(0);
            //移除指定位置的元素
            array.RemoveAt(1);//参数为下标
            //清空
            //array.Clear();//把list容器里的元素清空
            //范围移除 从下标1开始移除两位
            //array.RemoveRange(1,2);
            #endregion

            #region 查
            //得到指定下标的元素  类似于数组 用下标拿到容器里的元素
            Console.WriteLine(array[0]);

            //判断元素是否存在
            if (array.Contains("123"))
            {
                Console.WriteLine("存在123");
            }

            //正向查找元素位置（下标）
            //找到的返回位置（下标） 找不到返回-1
            int index = array.IndexOf(true);//这里有两个true 但是只显示了第一个true的位置（下标），所以是正向查找
            Console.WriteLine(index);//返回下标 1

            Console.WriteLine(array.IndexOf("许丰"));//查找不到 返回-1

            //反向查找元素位置(下标)
            index = array.LastIndexOf(true);//返回最后一个true的位置(下标,索引)
            Console.WriteLine(index);//返回下标 4
            #endregion

            #region 改 
            //类似数组 直接赋值修改
            Console.WriteLine(array[0]);
            //通过指定元素的下标去修改
            array[0] = "许丰";
            Console.WriteLine(array[0]);
            #endregion

            #region 遍历
            //获取list容器元素的长度
            Console.WriteLine(array.Count);
            //获取list容器的容量 容量一定比长度大
            //容量的目的：避免产生过多的垃圾
            Console.WriteLine(array.Capacity);

            Console.WriteLine("***************分割线**************");
            //遍历list容器里的内容 跟数组差不多
            for (int i = 0; i < array.Count; i++)
            {
                Console.WriteLine(array[i]);
            }
            Console.WriteLine("***************分割线:迭代器遍历**************");
            //迭代器遍历
            foreach (var value in array)
            {
                Console.WriteLine(value);
            }
            #endregion

            #endregion

            #region 知识点四 装箱拆箱
            //ArrayList本质上是一个可以自动扩容的object数组  什么都可以装
            //由于用万物之父来存储数据，自然存在装箱拆箱
            //当往其中进行值类型存储是就是在装箱，当将值类型对象取出来转换使用时，就存在拆箱
            //(引用转为值类型即为拆箱，值类型转换为引用类型即为装箱)
            //所以ArrayList尽量少用，之后我们会学习更好的数据容器

            int j = 1;
            array[0] = j;//装箱 把栈上面的内存转移到堆上面

            j = (int)array[0];//拆箱 把堆上面的内存转移到栈上面
            #endregion

            #region  练习题
            //简述ArrayList与数组的区别
            /*
             * ArrayList可以存储类型不同的元素
             * 数组只能存储声明好的类型
             * arrayList的容量不够用之后直接扩展一倍容量
             * 在声明数组的时候必须指定数组的长度，数组的长度过长，会造成内存浪费，过段会造成数据溢出的错误
             * ArrayList在存储或检索值类型时通常发生装箱和取消装箱操作，带来很大的性能耗损。
             */

            //创建一个背包管理类，使用ArrayList存储物品，实现购买物品，卖出物品，显示物品的功能，购买与卖出物品会导致金钱变化
            Backpack backpack = new Backpack();//声明背包类；
            //购买物品
            Console.WriteLine(backpack.wallet);
            backpack.Buy("倚天剑", 250);
            backpack.Buy("屠龙刀", 250);
            backpack.Sale("葵花宝典",500);
            backpack.Show();
            #endregion
            Console.ReadKey();
        }
    }
}
